﻿using System;

/*
 * 创建人：
 * 
 * 时间：
 * 
 * 说明：
 * 
 * 
 * 修改说明：
 * 
 * 
 */


namespace ConsoleTest.ChapterFive
{
    /// <summary>
    /// NET同步机制
    /// </summary>
    public class Synchronous
    {
        /*
         * 为什么需要进行同步？
         * 在多线程程序中，对于局部变量只有内部线程可以访问，一般不需要同步
         * 对于只读的数据一般来讲也是不需要进行同步的。
         * 对于其他又读又写的数据需要进行同步，另外同步机制可以解决因为资源争用而发生的死锁问题。
         */

        /*
         * 应用程序的线程对于资源的访问可能会因为资源争用而发生冲突
         * 同步对象的目的在于阻塞部分线程，使另一个线程可以访问资源
         */

        /// <summary>
        /// 无同步机制测试
        /// 
        /// </summary>
        public static void NonSynchronized()
        {
            //无同步机制测试
            int a = 0;
            System.Threading.Thread t1 = new System.Threading.Thread(IncreamentNonSync);
            System.Threading.Thread t2 = new System.Threading.Thread(DecreamentNonSync);
            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }
        #region NonSync
        private static int nonSync = 0;
        private static void IncreamentNonSync()
        {
            for (int i = 0; i < 10; i++)
            {
                nonSync++;
                System.Console.WriteLine("Thread Increament:"+nonSync.ToString());
            }
        }
        private static void DecreamentNonSync()
        {
            for (int i = 0; i < 10; i++)
            {
                nonSync--;
                System.Console.WriteLine("Thread Decreament:" + nonSync.ToString());
            }
        }
        #endregion

        /// <summary>
        /// System.Threading.InterLocked
        /// Interlocked为多个线程共享的变量提供原子操作
        /// (因为一般性的原子操作的数据都是整型值，该类能够提供对变量的原子操作)
        /// </summary>
        public static void InterLocked()
        {
            System.Threading.Thread t1 = new System.Threading.Thread(InterLockedFun1);
            System.Threading.Thread t2 = new System.Threading.Thread(InterLockedFun2);
            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }

        #region InterLocked

        //静态变量
        private static long InterLockedcounter = 1;

        /// <summary>
        /// 操作counter变量 增加
        /// </summary>
        private static void InterLockedFun1()
        {
            for (int i = 0; i < 5; i++)
            {
                System.Threading.Interlocked.Increment(ref InterLockedcounter);
                System.Console.WriteLine("counter ++{0}", InterLockedcounter);
                //挂起10毫秒，这样不会在一个时间片内执行完所有的计算
                System.Threading.Thread.Sleep(10);
            }
        }

        /// <summary>
        /// 操作counter变量 减少
        /// </summary>
        private static void InterLockedFun2()
        {
            for (int i = 0; i < 5; i++)
            {
                System.Threading.Interlocked.Decrement(ref InterLockedcounter);
                System.Console.WriteLine("counter -- {0}", InterLockedcounter);
                //挂起10毫秒，这样不会在一个时间片内执行完所有的计算
                System.Threading.Thread.Sleep(10);
            }
        }

        #endregion

        /// <summary>
        /// Monitor 提供同步访问对象的机制
        /// </summary>
        public static void Monitor()
        {
            /*
             * Monitor 类通过向单个线程授予对象锁来控制对对象的访问。
             * 对象锁提供限制访问代码块（通常称为临界区）的能力。
             * 当一个线程拥有对象的锁时，其他任何线程都不能获取该锁。
             * 还可以使用 Monitor 来确保不会允许其他任何线程访问正在由锁的所有者执行的应用程序代码节，
             * 除非另一个线程正在使用其他的锁定对象执行该代码。
             */

            /*
             * 锁定对象时一般选择锁定对象内部私有变量，因为锁定对象本身可能导致死锁。
             */

            System.Threading.Thread t1 = new System.Threading.Thread(MonitorFun1);
            System.Threading.Thread t2 = new System.Threading.Thread(MonitorFun2);
            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }

        #region Monitor

        private static int MonitorCounter = 1;
        /// <summary>
        /// 
        /// </summary>
        private static void MonitorFun1()
        {
            for (int i = 0; i < 5; i++)
            {
                //提供同步访问对象的机制
                System.Threading.Monitor.Enter(typeof(global::ConsoleTest.Program));
                //System.Threading.Monitor.TryEnter(typeof(global::ConsoleTest.Program));
                try
                {
                    MonitorCounter *= MonitorCounter;
                }
                finally
                {
                    System.Threading.Monitor.Exit(typeof(global::ConsoleTest.Program));
                }
                System.Console.WriteLine("counter^2 {0}", MonitorCounter);
                System.Threading.Thread.Sleep(10);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        private static void MonitorFun2()
        {
            for (int i = 0; i < 5; i++)
            {
                //提供同步访问对象的机制
                System.Threading.Monitor.Enter(typeof(global::ConsoleTest.Program));
                //System.Threading.Monitor.TryEnter(typeof(global::ConsoleTest.Program));
                try
                {
                    MonitorCounter *= 2;
                }
                finally
                {
                    System.Threading.Monitor.Exit(typeof(global::ConsoleTest.Program));
                }
                System.Console.WriteLine("counter*2 {0}", MonitorCounter);
                System.Threading.Thread.Sleep(10);
            }
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        public static void Locked()
        {
            System.Threading.Thread t1 = new System.Threading.Thread(LockedFun1);
            System.Threading.Thread t2 = new System.Threading.Thread(LockedFun2);
            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }

        #region Locked
        private static long Lockedcounter = 1;

        /*
         * locked 关键字会引导编译器创建出相应的try/finally块
         * 这样仍旧可以预期到任何可能引发的异常
         * 
         * lock 关键字实现原理仍旧是使用 System.Threading.Monitor类的Enter和Exit方法来进行
         * 临界区的控制
         */

        private static void LockedFun1()
        {
            for (int i = 0; i < 5; i++)
            {
                lock (typeof(global::ConsoleTest.Program))
                {
                    Lockedcounter *= Lockedcounter;
                }
                System.Console.WriteLine("counter^2{0}", Lockedcounter);
                System.Threading.Thread.Sleep(10);
            }
        }

        private static void LockedFun2()
        {
            for (int i = 0; i < 5; i++)
            {
                lock (typeof(global::ConsoleTest.Program))
                {
                    Lockedcounter *= 2;
                }
                System.Console.WriteLine("counter*2{0}", Lockedcounter);
                System.Threading.Thread.Sleep(10);
            }
        }
        #endregion


        /// <summary>
        /// 使用SyncRoot模式进行共享数据的同步
        /// </summary>
        public static void SyncRoot()
        {
            /*
             * SyncRoot模式的实质是：在类的内部提供一个object类型的对象，外部对象可以
             * 使用lock关键字锁定该对象，实现对数据共享的同步
             */

            ClassOfSyncRoot cla = new ClassOfSyncRoot();
            System.Threading.Thread t1 = new System.Threading.Thread(cla.Increment);
            System.Threading.Thread t2 = new System.Threading.Thread(cla.Decrement);

            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }

        /// <summary>
        /// .NET的实现中，部分类提供了Synchronized方法以返回该类的线程安全封装类
        /// </summary>
        public static void SynchronizedClass()
        {
            //返回已经实现了线程同步的安全类
            System.Collections.Hashtable hash = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
        }

        /// <summary>
        /// 通过乒乓来实现对Wait、Pulse和PulseAll方法的模拟
        /// </summary>
        public static void PingPong()
        {
            System.Threading.Thread t1 = new System.Threading.Thread(Ping);
            System.Threading.Thread t2 = new System.Threading.Thread(Pong);
            t1.Start();
            t2.Start();
            //Join 方法阻塞主调线程，直到被调用线程终止
            t1.Join();
            t2.Join();
        }

        #region Pingpong
        private static object ball = new object();

        /*
         * 两个线程中首先获得执行线程的wait方法会被后获得线程的执行方法的pulse方法
         * 的锁的释放而获得执行；后获得ball访问权的线程因为处于wait状态所以最后没有结束
         */

        private static void Ping()
        {
            System.Console.WriteLine("Ping Thread Hello!");
            lock (ball)
            //使用lock关键字后由编译器自动生成Enter和Exit代码，及try和finally组合
            {
                for (int i = 0; i < 5; i++)
                {
                    System.Console.WriteLine("Ping");
                    //通知等待线程锁定对象的状态已更改，并且锁的所有者准备释放该锁
                    System.Threading.Monitor.Pulse(ball);
                    System.Threading.Monitor.Wait(ball);
                }
            }
            System.Console.WriteLine("Ping Bye!");
        }
        private static void Pong()
        {
            System.Console.WriteLine("Pong Thread Hello!");
            lock (ball)
            //使用lock关键字后由编译器自动生成Enter和Exit代码，及try和finally组合
            {
                for (int i = 0; i < 5; i++)
                {
                    System.Console.WriteLine("Pong");
                    //通知等待线程锁定对象的状态已更改，并且锁的所有者准备释放该锁
                    System.Threading.Monitor.Pulse(ball);
                    System.Threading.Monitor.Wait(ball);
                }
            }
            System.Console.WriteLine("Pong Bye!");
        }
        #endregion


        /*
        * 可以使用 Mutex 对象提供对资源的独占访问。Mutex 类比 Monitor 类使用更多系统资源，
         * 但是它可以跨应用程序域边界进行封送处理，可用于多个等待，并且可用于同步不同进程中的线程。
        */

        /// <summary>
        /// 使用互斥体实现同步 Mutual Exclusion 相互排斥
        /// </summary>
        public static void Mutex()
        {


            /*
             * 系统中的互斥体可以分为两类：有名互斥体和无名互斥体。无名互斥体仅在进程内可见，进程内的所有线程都可以使用。
             * 可以通过使用 接受string的构造函数创建有名互斥体，有名互斥体在操作系统内可见。并且在使用接受字符串的构造函数创建
             * 有名互斥体时，如果操作系统已经存在该互斥体时，操作系统不会创建该互斥体而是创建一个对互斥体的引用。
             * 
             * 
             * 互斥体当前线程如果意外终止，那么互斥体的状态被设置为signaled，并且互斥体会被放弃。其他线程是可以使用的。
             * 在.NET 2.0版本中下一个获得mutex的线程会引发一个AbandonedMutexException的异常，以前版本不会引发异常。
             */

            try
            {
                if (System.Threading.Mutex.OpenExisting("MyMutex") != null)
                {
                    System.Console.WriteLine("Named MyMutex exist!");
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("Named MyMutex not exist!");
            }
            

            System.Threading.Mutex mutex = new System.Threading.Mutex(false, "MyMutex");
            
            for (int i = 0; i < 10; i++)
            {
                //阻塞当前线程，直到该线程获得mutex所有权
                mutex.WaitOne();
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(@"..\..\5-进程线程与同步\mutex.txt");
                System.IO.StreamWriter sw = fileInfo.AppendText();
                sw.WriteLine("mutex:{0}{1}", mutex.Handle.ToInt64().ToString(), i);
                sw.Flush();
                sw.Close();
                System.Console.WriteLine("mutex:{0}{1}",mutex.Handle.ToInt64().ToString(),i);
                System.Threading.Thread.Sleep(1000);
                mutex.ReleaseMutex();
            }
            mutex.Close();
        }

        /// <summary>
        /// EventReset
        /// </summary>
        public static void EventReset()
        {
            /*
             * ManualResetEvent 和 AutoResetEvent通过发信号互相通信
             * 通过waitone或者waitall来等待信号
             */
            events=new System.Threading.EventWaitHandle[2];
            //如果 AutoResetEvent 为非终止状态，则线程会被阻止
            //可以理解为：非终止时其他线程在用，所以请求线程会被终止

            //通过给EventWaitHandle类传递枚举实现对子类的构造。ManualResetEvent和AutoResetEvent都继承自EventWaitHandle
            //集成层次如下：
            //                      System.Object
            //                      System.MarshalByRefObject
            //                      System.Threading.WaitHandle
            //                      System.Threading.EventWaitHandle
            //                      System.Threading.AutoResetEvent
            events[0] = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset);
            events[1] = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset);

            System.Threading.Thread t1 = new System.Threading.Thread(EventResetFun1);
            System.Threading.Thread t2 = new System.Threading.Thread(EventResetFun2);
            t1.Start();
            t2.Start();
            //等待所有指定的列表中的元素收到信号
            System.Threading.AutoResetEvent.WaitAll(events);
            //注意System.Console.WriteLine("Fun1 reached 2 and Fun2 reached 3 "); 写在 join方法之前
            //否则主线程会等待两个子线程运行接受后才能够输出
            System.Console.WriteLine("Fun1 reached 2 and Fun2 reached 3 ");
            t1.Join();
            t2.Join();
        }
        #region EventReset
        private static System.Threading.EventWaitHandle[] events;
        private static void EventResetFun1()
        {
            for (int i = 0; i < 5; i++)
            {
                System.Console.WriteLine("EventResetFun1 :{0}",i);
                if (i == 2)
                    //将事件设置为终止状态，允许一个或者多个其他线程继续
                    events[0].Set();
                System.Threading.Thread.Sleep(100);
            }
        }
        private static void EventResetFun2()
        {
            for (int i = 0; i < 5; i++)
            {
                System.Console.WriteLine("EventResetFun2 :{0}", i);
                if (i ==3)
                    //将事件设置为终止状态，允许一个或者多个其他线程继续
                    events[1].Set();
                System.Threading.Thread.Sleep(100);
            }
        }
        #endregion

        /// <summary>
        /// net中的信号量同步机制
        /// </summary>
        public static void Semaphore()
        {
            /*
             * 类似互斥锁，但它可以允许多个线程同时访问一个共享资源
            * 通过使用一个计数器来控制对共享资源的访问，如果计数器大于0，就允许访问，如果等于0，就拒绝访问。
             * 计数器累计的是“许可证”的数目，为了访问某个资源。线程必须从信号量获取一个许可证。
             * 通常在使用信号量时，希望访问共享资源的线程将尝试获取一个许可证，
             * 如果信号量的计数器大于0，线程将获取一个许可证并将信号量的计数器减1，否则先线程将阻塞，
             * 直到获取一个许可证；当线程不再需要共享资源时，将释放锁拥有的许可证，并将许可证的数量加1，
             * 如果有其他的线程正在等待许可证，那么该线程将立刻获取许可证。
             * 另外，允许同时访问的资源的进程数量是在创建信号量时指定的，
             * 
             * 
             * (注意：)如果创建一个允许进程访问的信号量数目为1，则该信号量就和互斥锁的用法一样。
             */
            /*
             * System.Threading.Semaphore 类表示一个命名（系统范围）信号量或本地信号量。
             * 它是一个对 Win32 信号量对象的精简包装。Win32 信号量是计数信号量，可用于控制对资源池的访问。
             */

            /*
             * 信号量同样具有本地信号量（无名信号量）和系统信号量（命名信号量）两种类型
             */

            semaphore = new System.Threading.Semaphore(2, 5);
            for (int i = 0; i < 3; i++)
            {
                System.Threading.Thread t = new System.Threading.Thread(SemaphoreWork);
                t.Name = "Thread" + i;
                t.Start();
                System.Threading.Thread.Sleep(30);
            }
        }

        #region Semaphore
        private static System.Threading.Semaphore semaphore;
        private static void SemaphoreWork()
        {
            for (int j = 0; j < 3; j++)
            {
                //阻止当前线程，直到遇到信号
                semaphore.WaitOne();
                System.Console.WriteLine(System.Threading.Thread.CurrentThread.Name + " Begin!");
                System.Threading.Thread.Sleep(200);//模拟一个200毫秒的任务
                System.Console.WriteLine(System.Threading.Thread.CurrentThread.Name + " End!");
                semaphore.Release();
            }
        }
        #endregion

        /// <summary>
        /// System.Threading.ReaderWriterLock类实现多用户读/单用户写的同步访问机制
        /// 该模型有别于Monitor和Mutex类型的独占访问模型
        /// </summary>
        public static void ReadWriterLock()
        {
            /*
             * ReaderWriterLock 用于对于共享资源的同步访问，允许多线程同时读单线程写。
             * The .NET Framework has two reader-writer locks, ReaderWriterLockSlim and ReaderWriterLock.
             * ReaderWriterLockSlim is recommended for all new development. ReaderWriterLockSlim is similar to ReaderWriterLock, 
             * but it has simplified rules for recursion and for upgrading and downgrading lock state. 
             * ReaderWriterLockSlim avoids many cases of potential deadlock. In addition, 
             * the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock. 
             */

            /*
             * A thread can hold a reader lock or a writer lock, but not both at the same time. 
             * Instead of releasing a reader lock in order to acquire the writer lock, you can use UpgradeToWriterLock and DowngradeFromWriterLock.
             */

            System.Threading.Thread t1 = new System.Threading.Thread(ReaderWriterLock_Write);
            System.Threading.Thread t2 = new System.Threading.Thread(ReaderWriterLock_Read);
            System.Threading.Thread t3 = new System.Threading.Thread(ReaderWriterLock_Read);
            t1.Name = "Writer";
            t2.Name = "Reader-1";
            t3.Name = "Reader-2";
            //System.Threading.Thread t1 = new System.Threading.Thread(ReaderWriterLockSlim_Write);
            //System.Threading.Thread t2 = new System.Threading.Thread(ReaderWriterLockSlim_Read);
            //System.Threading.Thread t3 = new System.Threading.Thread(ReaderWriterLockSlim_Read);

            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
        }
        #region ReaderWriter
        private static System.Threading.ReaderWriterLock rw1 = new System.Threading.ReaderWriterLock();
        private static System.Threading.ReaderWriterLockSlim rws1 = new System.Threading.ReaderWriterLockSlim();
        private static string path = @"..\..\5-进程线程与同步\ReaderWriter.txt";
        private static System.IO.FileInfo fileSource = new System.IO.FileInfo(path);
        private static void ReaderWriterLockSlim_Read()
        {
            try
            {
                for (int i = 0; i < 5; i++)
                {
                    rws1.EnterReadLock();
                    if (System.IO.File.Exists(path))
                    {
                        string str= System.IO.File.ReadAllText(path);
                        System.Console.WriteLine("Reader:{0} read text  \n"+str,System.Threading.Thread.CurrentThread.Name);
                    }
                    else
                    {
                        System.Console.WriteLine("file not exist! ");
                    }


                    rws1.ExitReadLock();

                }
            }
            catch (System.ApplicationException exc)
            {
                System.Console.WriteLine(exc.Message);
            }
        }
        private static void ReaderWriterLockSlim_Write()
        {
            System.Random rd=new Random();
            try
            {
                for (int i = 0; i < 5; i++)
                {
                    rws1.EnterWriteLock();
                    System.IO.StreamWriter sw = fileSource.AppendText();
                    System.Console.WriteLine("Begin write:");
                    System.Console.WriteLine("write text:"+rd.Next());
                    System.Threading.Thread.Sleep(100);
                    System.Console.WriteLine("end write");
                    sw.Flush();
                    sw.Close();
                    rws1.ExitWriteLock();
                }
                
            }
            catch (System.ApplicationException exc)
            {
                System.Console.WriteLine(exc.Message);
            }
        }
        private static void ReaderWriterLock_Read()
        {
            try
            {
                for (int i = 0; i < 5; i++)
                {
                    rw1.AcquireReaderLock(1000);
                    if (System.IO.File.Exists(path))
                    {
                        string str = System.IO.File.ReadAllText(path);
                        System.Console.WriteLine("Reader:{0} read text  \n" + str, System.Threading.Thread.CurrentThread.Name);
                    }
                    else
                    {
                        System.Console.WriteLine("file not exist! ");
                    }
                    rw1.ReleaseReaderLock();
                }

            }
            catch (System.ApplicationException exc)
            {
                System.Console.WriteLine(exc.Message);
            }
        }
        private static void ReaderWriterLock_Write()
        {
            System.Random rd = new Random();
            try
            {
                for (int i = 0; i < 5; i++)
                {
                    rw1.AcquireWriterLock(1000);
                    System.IO.StreamWriter sw = fileSource.AppendText();
                    int val = rd.Next();
                    System.Console.WriteLine("Begin write:");
                    System.Console.WriteLine("write text:" + val);
                    sw.WriteLine(val);
                    System.Threading.Thread.Sleep(100);
                    System.Console.WriteLine("end write");
                    sw.Flush();
                    sw.Close();
                    rw1.ReleaseWriterLock();
                }

            }
            catch (System.ApplicationException exc)
            {
                System.Console.WriteLine(exc.Message);
            }
        }
        #endregion

        /// <summary>
        /// 线程安全类
        /// </summary>
        public static void ThreadSafeClass()
        {
            System.Threading.Thread t1 = new System.Threading.Thread(ThreadSafeFun);
            System.Threading.Thread t2 = new System.Threading.Thread(ThreadSafeFun);
            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }
        #region ThreadSafe
        private static ThreadSafeClass SafeClass = new ThreadSafeClass();
        private static void ThreadSafeFun()
        {
            for (int i = 0; i < 5; i++)
                SafeClass.DisplayThreadId();
        }
        #endregion 

        /// <summary>
        /// 线程池
        /// </summary>
        public static void ThreadPool()
        {
            /*
             * “线程池”是可以用来在后台执行多个任务的线程集合。（有关背景信息，请参见使用线程处理。）
             * 这使主线程可以自由地异步执行其他任务。
             * 线程池通常用于服务器应用程序。每个传入请求都将分配给线程池中的一个线程，
             * 因此可以异步处理请求，而不会占用主线程，也不会延迟后续请求的处理。 
             * 一旦池中的某个线程完成任务，它将返回到等待线程队列中，等待被再次使用。
             * 这种重用使应用程序可以避免为每个任务创建新线程的开销。
             * 线程池通常具有最大线程数限制。如果所有线程都繁忙，则额外的任务将放入队列中，
             * 直到有线程可用时才能够得到处理。
             * 您可以实现自己的线程池，但是通过 ThreadPool 类使用 .NET Framework 提供的线程池更容易一些。 
             * 下面的示例使用 .NET Framework 线程池计算 20 和 40 之间的十个数的 Fibonacci 结果。
             * 每个 Fibonacci 结果都由 Fibonacci 类表示，该类提供一种名为 ThreadPoolCallback 的方法来执行此计算。将创建表示每个 Fibonacci 值的对象，ThreadPoolCallback 方法将传递给 QueueUserWorkItem，它分配池中的一个可用线程来执行此方法。
             * 由于为每个 Fibonacci 对象都提供了一个半随机值来进行计算，而且十个线程都将竞争处理器时间，
             * 因此无法提前知道十个结果全部计算出来所需的时间。
             * 因此在构造期间为每个 Fibonacci 对象传递 ManualResetEvent 类的一个实例。
             * 当计算完成时，每个对象都通知提供的事件对象，使主线程用 WaitAll 阻止执行，
             * 直到十个 Fibonacci 对象全部计算出了结果。然后 Main 方法将显示每个 Fibonacci 结果。
             */

            System.Threading.ThreadPool.RegisterWaitForSingleObject(new System.Threading.AutoResetEvent(false)
            , new System.Threading.WaitOrTimerCallback(ThreadTaskWait) 
            , null, 2000, false);

            for (int count = 0; count < 3; ++count)
            {
                //将方法排入队列，此方法在线程池中线程变得可用时执行
                System.Threading.ThreadPool.QueueUserWorkItem(
                    new System.Threading.WaitCallback(ThreadTask)
                    , count);

                System.Threading.Thread.Sleep(12000);
            }
        }
        #region ThreadPool
        private static void ThreadTask(object obj)
        {
            System.Console.WriteLine("Thread#{0} Task#{1} begin",System.Threading.Thread.CurrentThread.ManagedThreadId
               ,obj.ToString());

            System.Threading.Thread.Sleep(5000);

            System.Console.WriteLine("Thread#{0} Task#{1} end", System.Threading.Thread.CurrentThread.ManagedThreadId
             , obj.ToString());
        }
        private static void ThreadTaskWait(object obj, bool signaled)
        {
            System.Console.WriteLine("Thread#{0} TaskWait",System.Threading.Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

    }

    /// <summary>
    /// Gets an object that can be used to synchronize access to the ICollection.
    /// 获取一个
    /// </summary>
    public class ClassOfSyncRoot
    {

        /*
         * 在类中可以通过使用 lock(this) 关键字来实现同步，这样多个线程尽可以以同步方式访问
         * 
         * SyncRoot 的私有成员可以设置为静态或者非静态成员
         * 
         * System.Collections.ICollection接口提供了object类型的SyncRoot{get;}属性
         * 
         * SyncRoot模式就是在类的内部设置一个私有变量，
         */
        private static object staticSyncRoot = new object();
        private object instanceSyncroot = new object();
        /// <summary>
        /// 
        /// </summary>
        public int ClassValue
        {
            get;
            set;
        }

        /// <summary>
        /// 增加
        /// </summary>
        public void Increment()
        {
            lock (instanceSyncroot)
            {
                for (int i = 0; i < 100; i++)
                {
                    this.ClassValue++;
                    System.Console.WriteLine("ClassValue:{0}", this.ClassValue);
                }
            }
        }

        /// <summary>
        /// 减少
        /// </summary>
        public void Decrement()
        {
            lock (instanceSyncroot)
            {
                for (int i = 0; i < 100; i++)
                {
                    this.ClassValue--;
                    System.Console.WriteLine("ClassValue:{0}", this.ClassValue);
                }
            }
        }

    }

    /// <summary>
    /// System.Runtime.Remoting.Contexts.Synchronization属性
    /// 实现线程安全类，线程安全类：同一时间只有单一的线程可以访问该类
    /// </summary>
    [System.Runtime.Remoting.Contexts.Synchronization(System.Runtime.Remoting.Contexts.SynchronizationAttribute.REQUIRED)]
    public class ThreadSafeClass : System.ContextBoundObject
    {
          /*
           * 能够使用该属性的类必须是上下文绑定的，即：它必须继承自System.ContextBoundObject类
           * 
           * 另外可以通过使用：SyncRoot模式实现线程安全类
           * SyncRoot模式：通过内部包含一个object对象，并对类的方法使用lock关键字实现同步
           * 
           */
        public void DisplayThreadId()
        {
            System.Console.WriteLine("Begin: ManagedthreadId ="+System.Threading.Thread.CurrentThread.ManagedThreadId);
            System.Threading.Thread.Sleep(1000);
            System.Console.WriteLine("End: ManagedthreadId =" + System.Threading.Thread.CurrentThread.ManagedThreadId);
        }
    }
}